package com.jason.www.disruptor.multievent;

import com.lmax.disruptor.EventTranslatorOneArg;
import com.lmax.disruptor.RingBuffer;
import com.lmax.disruptor.dsl.Disruptor;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextClosedEvent;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

import static com.jason.www.commons.DisruptorUtil.createDisruptor;
import static com.jason.www.commons.DisruptorUtil.shutDownDisruptor;
import static com.jason.www.commons.FinalCleanEventSourceHandler.CLEAN_EVENT_HANDLER;

/**
 * 可以同时执行一个Disrupter 多个Handler（异步执行多个逻辑）
 */
@Component
public class MultiEventDisruptor implements InitializingBean, ApplicationListener<ContextClosedEvent> {
    private Disruptor<MultiEvent> disruptor;
    private EventTranslatorOneArg<MultiEvent, String> translatorOneArg;
    private RingBuffer<MultiEvent> ringBuffer;

    @Autowired(required = false)
    private List<MultiEventHandler> handlers = new ArrayList<>(16);

    @Override
    public void afterPropertiesSet(){
        disruptor = createDisruptor(MultiEvent::new, 1 << 9);
        disruptor.handleEventsWith(handlers.toArray(new MultiEventHandler[0]))
                .then(CLEAN_EVENT_HANDLER);
        disruptor.start();
        ringBuffer = disruptor.getRingBuffer();
        translatorOneArg = (event, sequence, msg) -> event.setMsg(msg);
    }

    @Override
    public void onApplicationEvent(ContextClosedEvent contextClosedEvent) {
        shutDownDisruptor(disruptor);
    }

    public void publish(String msg) {
        ringBuffer.publishEvent(translatorOneArg, msg);
    }
}
